﻿#region imports

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Services;
using System.Globalization;
using System.Linq;
using Codeplex.ODataTFS.Model.Entities;
using Codeplex.ODataTFS.Model.ExpressionVisitors;
using Codeplex.ODataTFS.Model.Serialization;
using Microsoft.Data.Services.Toolkit.QueryModel;

#endregion

namespace Codeplex.ODataTFS.Model.Repositories
{
	public class WorkItemRepository
	{
		private readonly TFSWorkItemProxy _proxy;

		public WorkItemRepository(TFSWorkItemProxy proxy)
		{
			_proxy = proxy;
		}

		public WorkItem GetOne(string id)
		{
			var workItemId = 0;
			if (!int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out workItemId))
			{
				throw new ArgumentException("The id parameter must be numeric", "id");
			}

			return _proxy.GetWorkItem(workItemId);
		}

		[RepositoryBehavior(HandlesFilter = true, HandlesSkip = true, HandlesTop = true, HandlesOrderBy = true)]
		public IEnumerable<WorkItem> GetWorkItemsByProject(ODataSelectManyQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var parameters = new WorkItemFilterExpressionVisitor(operation.FilterExpression).Eval();
			return _proxy.GetWorkItemsByProject(operation.Key, parameters, operation);
		}

		[RepositoryBehavior(HandlesSkip = true, HandlesTop = true)]
		public IEnumerable<WorkItem> GetWorkItemsByQuery(ODataSelectManyQueryOperation operation)
		{
			var queryId = default(Guid);
			if (!Guid.TryParse(operation.Keys["id"], out queryId))
			{
				throw new ArgumentException("The id paramter must be a GUID", "id");
			}

			return _proxy.GetWorkItemsByQuery(queryId, operation);
		}

		public IEnumerable<WorkItem> GetWorkItemsByChangeset(string id)
		{
			var changesetId = 0;
			if (!int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out changesetId))
			{
				throw new ArgumentException("The id parameter must be numeric", "id");
			}

			return _proxy.GetWorkItemsByChangeset(changesetId);
		}

		[RepositoryBehavior(HandlesFilter = true)]
		public IEnumerable<WorkItem> GetWorkItemsByBuild(ODataSelectManyQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var parameters = new WorkItemFilterExpressionVisitor(operation.FilterExpression).Eval();
			return _proxy.GetWorkItemsByBuild(operation.Keys["project"], operation.Keys["number"], parameters);
		}

		[RepositoryBehavior(HandlesFilter = true, HandlesSkip = true, HandlesTop = true, HandlesOrderBy = true)]
		public IEnumerable<WorkItem> GetAll(ODataQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var filterParameters = new WorkItemFilterExpressionVisitor(operation.FilterExpression).Eval();
			return _proxy.GetWorkItemsByProjectCollection(filterParameters, operation);
		}

		public object CreateDefaultEntity()
		{
			return new WorkItem();
		}

		public void CreateRelation(object targetResource, object resourceToBeAdded)
		{
			throw new DataServiceException(501, "Not Implemented", "'CreateRelation' Operation in the WorkItem Repository is not supported", "en-US", null);
		}

		public void Remove(object entity)
		{
			throw new DataServiceException(501, "Not Implemented", "The WorkItems cannot be deleted", "en-US", null);
		}

		public void Save(object entity)
		{
			var workItem = entity as WorkItem;
			if (workItem == null)
			{
				workItem = (entity as IEnumerable).Cast<WorkItem>().First();
			}

			if (workItem.Id > 0)
			{
				_proxy.UpdateWorkItem(workItem);
			}
			else
			{
				_proxy.CreateWorkItem(workItem);
			}
		}
	}
}
